import random
import requests

from django.conf import settings
from django.http import HttpResponseRedirect
from django.http import HttpResponse
from django.shortcuts import redirect
from django.shortcuts import render

from . import helpers
from entities import banner_mgr
from entities import egg_mgr
from entities import pay_mgr
from entities import redis_mgr
from entities import registration_mgr
from entities import sms_mgr
from entities import unipay_mgr
from entities import user_mgr
from entities import version_mgr
from utils import ajax
from utils import util
from utils.log import Log

from urllib import parse


def pay_list(request, uid, ptype):
    """ 充值页面 """
    context = helpers.build_context(request)
    context['uid'] = uid
    context['type'] = ptype
    return render(request, 'mweb/pay_list.html', context)


def confirm(request, uid, rmb, ptype):
    """ 支付确认页面 """
    context = helpers.build_context(request)
    context['uid'] = int(uid)
    context['rmb'] = int(rmb)

    if ptype == 'wx':
        return render(request, 'mweb/pay_wx_confirm.html', context)
    elif ptype == 'ali':
        # return redirect('https://www.yyzb.com/pay/index.html#/?status=success')
        return redirect('https://res.yyzb.com/tool/aliwap/index.html#/?status=success')
    elif ptype == 'uni':
        return redirect('https://res.yyzb.com/tool/unipaymp/index.html#/?status=success')
    else:
        return helpers.show_warn_page(request, '无效的类型!')
        # return render(request, 'mweb/pay_ali_confirm.html', context)


def api_pay(request):
    """ 支付 """
    # return helpers.show_warn_page(request, '系统维护中!')

    uid = int(request.POST['uid'].strip())
    rmb = int(request.POST['rmb'].strip())
    wap_name = request.POST['wap_name'].strip()
    client_ip = util.get_request_real_ip(request)[0]

    # 检测用户id是否合法
    if not user_mgr.is_valid_uid(uid):
        return ajax.error_response('无效的用户ID！')

    # 创建订单
    params = pay_mgr.pay_with_weixin_h5(uid, rmb, client_ip, wap_name)
    if params is None:
        return ajax.error_response('支付失败！')

    url = params['mweb_url']
    return_url = parse.quote(settings.WX_RETURN_URL % (uid, rmb))
    url += '&&redirect_url=' + return_url
    params['mweb_url'] = url

    return ajax.success_response(params)

def pay_with_official_alipay(request, uid, rmb):
    """ 使用支付宝原生进行支付 """
    # return helpers.show_warn_page(request, '系统维护中!')

    uid = int(uid)
    rmb = int(rmb)

    # ----------------------------
    # 支付宝原生支付
    # ----------------------------

    # 检测用户id是否合法
    if not user_mgr.is_valid_uid(uid):
        return helpers.show_warn_page(request, '无效的用户ID!')

    # 检测充值金额
    if rmb <= 0:
        return helpers.show_warn_page(request, '无效的充值金额!')

    # 创建订单，并重定向到支付宝支付页面
    response = pay_mgr.pay_with_ali_h5(uid, rmb)
    Log.info(f"Alipay response: {response}")
    return HttpResponseRedirect(response)


def pay_with_uni_alipay(request, uid, rmb):
    """ 使用支付宝进行支付 """
    uid = int(uid)
    rmb = int(rmb)

    # ----------------------------
    # 银联支付宝H5支付
    # ----------------------------

    return pay_with_unipay_ali(request, uid, rmb)

    # # ----------------------------
    # # 支付宝原生支付
    # # ----------------------------
    #
    # # 检测用户id是否合法
    # if not user_mgr.is_valid_uid(uid):
    #     return helpers.show_warn_page(request, '无效的用户ID!')
    #
    # # 检测充值金额
    # if rmb <= 0:
    #     return helpers.show_warn_page(request, '无效的充值金额!')
    #
    # # 检测请求ip是否合法
    # # client_ip = util.get_request_real_ip(request)[0]
    # # key = redis_mgr.KEY_USER_PAY_IP % uid
    # # cached_pay_ip = redis_mgr.get_cached_string(key)
    # # if client_ip != cached_pay_ip:
    # #     return helpers.show_warn_page(request, f'充值异常! 您正在充值￥{rmb}给账号{uid}, 请确认这是否是您自己的账号。')
    #
    # # 创建订单，并重定向到支付宝支付页面
    # response = pay_mgr.pay_with_ali_h5(uid, rmb)
    # Log.info(f"Alipay response: {response}")
    # return HttpResponseRedirect(response)


def pay_with_unipay_mp(request, uid, rmb):
    """ 使用银联进行公众号充值 """
    # return helpers.show_warn_page(request, '系统维护中!')

    Log.info(f'Unipay mp: uid={uid}, rmb={rmb}')
    uid = int(uid)
    rmb = int(rmb)

    # if uid not in settings.TEST_UIDS_FOR_PAY:
    #     return helpers.show_warn_page(request, '尽请期待!')

    # 创建 out_trade_no
    out_trade_no = unipay_mgr.create_order_no(uid, rmb, settings.UNIPAY_MSG_SRC_ID)
    if out_trade_no is None:
        Log.error('Fetch out_trade_no from api-server failed!')
        return helpers.show_warn_page(request, '创建订单失败!')
    Log.info(f'Fetch out_trade_no for unipay mp from api-server: {out_trade_no}!')

    # 处理测试账号的充值金额
    amount = 100*rmb
    if uid in settings.TEST_UIDS_FOR_PAY:
        amount = 1

    url = settings.UNIPAY_URL
    params = {
        # 消息来源
        'msgSrc': settings.UNIPAY_MSG_SRC,
        # 消息类型(非必传: WXPay.jsPay :微信公众号支付, trade.jsPay :支付宝, acp.jsPay :银联云闪付)
        'msgType': 'WXPay.jsPay',
        # 报文请求时间，格式yyyy-MM-dd HH:mm:ss
        'requestTimestamp': util.now(),
        # 商户订单号, 长度6到32位
        'merOrderId': out_trade_no,
        # 商户号
        'mid': settings.UNIPAY_MID,
        # 终端号
        'tid': settings.UNIPAY_TID,
        # 业务类型
        'instMid': settings.UNIPAY_INST_MID,
        # 支付总金额，单位分
        'totalAmount': amount,
        # 支付结果通知地址
        'notifyUrl': settings.UNIPAY_NOTIFY_URL,
        # 网页跳转地址
        'returnUrl': f'https://m.yyzb.com/mweb/pay/{uid}/{rmb}/uni/confirm/',
    }
    sign = unipay_mgr.build_sign(params, settings.UNIPAY_SECRET)
    params['sign'] = sign
    Log.info(f'GET unipay: url={url}, params={params}')

    t = []
    for k, v in params.items():
        t.append(f'{k}={v}')
    request_url = f'{url}?' + '&'.join(t)
    Log.info(f'redirect to : {request_url}')
    return HttpResponseRedirect(request_url)


def pay_with_unipay_ali(request, uid, rmb):
    """ 使用银联在官网H5页面使用支付宝充值 """
    Log.info(f'Unipay mp: uid={uid}, rmb={rmb}')
    uid = int(uid)
    rmb = int(rmb)

    # if uid not in settings.TEST_UIDS_FOR_PAY:
    #     return helpers.show_warn_page(request, '尽请期待!')

    # 创建 out_trade_no
    out_trade_no = unipay_mgr.create_order_no_for_alipay_h5(uid, rmb, settings.UNIPAY_MSG_SRC_ID)
    if out_trade_no is None:
        Log.error('Fetch out_trade_no from api-server failed!')
        return helpers.show_warn_page(request, '创建订单失败!')
    Log.info(f'Fetch out_trade_no for unipay H5 alipay from api-server: {out_trade_no}!')

    # 处理测试账号的充值金额
    amount = 100*rmb
    if uid in settings.TEST_UIDS_FOR_PAY:
        amount = 1

    url = settings.UNIPAY_URL
    params = {
        # 消息来源
        'msgSrc': settings.UNIPAY_MSG_SRC,
        # 消息类型(支付宝H5支付: trade.h5Pay, 微信H5支付: WXPay.h5Pay, 银联在线无卡: qmf.h5Pay, 银联云闪付（走银联全渠道）: uac.order)
        'msgType': 'trade.h5Pay',
        # 报文请求时间，格式yyyy-MM-dd HH:mm:ss
        'requestTimestamp': util.now(),
        # 商户订单号, 长度6到32位
        'merOrderId': out_trade_no,
        # 商户号
        'mid': settings.UNIPAY_MID,
        # 终端号
        'tid': settings.UNIPAY_TID,
        # 业务类型
        'instMid': "H5DEFAULT",
        # 支付总金额，单位分
        'totalAmount': amount,
        # 支付结果通知地址
        'notifyUrl': settings.UNIPAY_NOTIFY_URL,
        # 网页跳转地址
        'returnUrl': 'https://res.yyzb.com/tool/aliwap/index.html#/',
    }
    sign = unipay_mgr.build_sign(params, settings.UNIPAY_SECRET)
    params['sign'] = sign
    Log.info(f'GET unipay: url={url}, params={params}')

    # 调用该接口时所有上送报文里的上送字段值，若包含了特殊字符的 须进行urlencode加密
    # （1. urlencode加密是utf-8格式； 2.只对上送报文的字段值进行加密，生成签名时的待签字串仍用原始字符）
    params['returnUrl'] = parse.quote(params['returnUrl'])

    t = []
    for k, v in params.items():
        t.append(f'{k}={v}')
    request_url = f'{url}?' + '&'.join(t)
    Log.info(f'redirect to : {request_url}')
    return HttpResponseRedirect(request_url)


def pay_with_wx(request, uid, rmb):
    """ 使用微信进行支付 """
    # return helpers.show_warn_page(request, '系统维护中!')

    uid = int(uid)
    rmb = int(rmb)
    wap_name = 'haibao'
    client_ip = util.get_request_real_ip(request)[0]

    # 检测用户id是否合法
    if not user_mgr.is_valid_uid(uid):
        return helpers.show_warn_page(request, '无效的用户ID!')

    # # 创建订单
    # params = pay_mgr.pay_with_weixin_h5(uid, rmb, client_ip, wap_name)
    # if params is None:
    #     return helpers.show_warn_page(request, '支付失败!')
    #
    # url = params['mweb_url']
    # return_url = parse.quote(settings.WX_RETURN_URL % (uid, rmb))
    # url += '&&redirect_url=' + return_url
    # return HttpResponseRedirect(url)

    context = helpers.build_context(request)
    context['uid'] = uid
    context['rmb'] = rmb
    context['type'] = 'wx'
    return render(request, 'mweb/pay_wx.html', context)


def exchange_rule(request):
    """ 兑换协议 """
    context = helpers.build_context(request)
    return render(request, 'mweb/rule/exchange_rule.html', context)


def identity_rule(request):
    """ 兑换协议 """
    context = helpers.build_context(request)
    return render(request, 'mweb/rule/identity.html', context)


def user_agreement(request):
    """ 兑换协议 """
    context = helpers.build_context(request)
    return render(request, 'mweb/rule/exchange_rule.html', context)


def privacy_agreement(request):
    """ 兑换协议 """
    context = helpers.build_context(request)
    return render(request, 'mweb/rule/exchange_rule.html', context)


def faq(request):
    """ 兑换协议 """
    context = helpers.build_context(request)
    return render(request, 'mweb/rule/faq.html', context)


def egg(request, egg_type = 0):
    """ 砸蛋规则 """
    egg_type = int(egg_type)

    # 规则内容
    rules = []
    if egg_type in [0, 1]:
        rules = [
            '1、您只可以使用锤子进行本游戏；',
            '2、点击“+”号可以使用金币购买锤子；',
            '3、您有机会在金蛋中获取各种高价值礼物及未上架礼物；',
            '4、高价值礼物会发送全服公告，您可以点击设置关闭公告；',
            '5、点击自动砸蛋会自动进行单次砸蛋并且扣除您锤子的数量；',
            '6、当您点击停止砸蛋，关闭砸蛋页面或锤子数量为0时自动砸蛋会停止。',
        ]
    elif egg_type in [2, 3]:
        rules = [
            '1、您只可以使用扭蛋币进行本游戏；',
            '2、点击“+”号可以使用金币购买扭蛋币；',
            '3、您有机会在扭蛋机中获取各种高价值礼物及未上架礼物；',
            '4、高价值礼物回发送全服公告，您可以点击设置关闭公告；',
            '5、点击自动扭蛋会自动进行单次扭蛋并且扣除您的扭蛋币数量；',
            '6、当您点击停止扭蛋，关闭扭蛋页面或扭蛋币数量为0时自动扭蛋会停止。',
        ]

    # 将礼物排成两列
    gifts = egg_mgr.get_egg_gift_display_probability(egg_type)
    gifts_count = len(gifts)
    gifts_two_lines = []
    for i in range(int(gifts_count/2)):
        if 2*i + 1 < gifts_count:
            gift1 = gifts[2*i]
            gift2 = gifts[2*i+1]
            row = [gift1[0], gift1[1], gift2[0], gift2[1]]
        else:
            gift1 = gifts[2*i]
            row = [gift1[0], gift1[1], '', '']
        gifts_two_lines.append(row)

    context = helpers.build_context(request)
    context['gifts'] = gifts_two_lines
    context['rules'] = rules

    return render(request, 'mweb/rule/egg.html', context)


def banner(request, banner_id):
    """ 显示banner """
    banner_id = int(banner_id)
    context = helpers.build_context(request)
    context['banner'] = banner_mgr.get_banner(banner_id)
    return render(request, 'mweb/banner.html', context)


def test(request):
    """ test """
    context = helpers.build_context(request)
    return render(request, 'mweb/test.html', context)


def hba_entry(request):
    """ 管理后台入口 """
    context = helpers.build_context(request)
    return render(request, 'mweb/entry/hba/index.html', context)


def guild_entry(request):
    """ 公会后台入口 """
    context = helpers.build_context(request)
    return render(request, 'mweb/entry/guild/index.html', context)


def registration(request, app, channel):
    """ 预注册 """
    # 提取版本下载地址
    ios_channel = 'iOS_HaiBao'
    android_channel = channel
    version_config = version_mgr.get_version_config(ios_channel, android_channel)
    ios_download_url = version_config.get('ios_download_url', None)
    if ios_download_url == '':
        return helpers.show_warn_page(request, '未发现iOS下载版本!')

    android_download_url = version_config.get('android_download_url', None)
    if android_download_url == '':
        return helpers.show_warn_page(request, '未发现安卓下载版本!')

    # 构造上下文
    context = helpers.build_context(request, has_fontawesome = False)
    context['app'] = app
    context['channel'] = channel
    context['ios_download_url'] = ios_download_url
    context['android_download_url'] = android_download_url

    # 渲染页面
    # return render(request, 'mweb/pre_registration.html', context)
    return render(request, 'mweb/registration.html', context)


def registration_v2(request, app, channel):
    """ 预注册v2版本 """
    # 提取版本下载地址
    ios_channel = 'iOS_HaiBao'
    android_channel = channel
    version_config = version_mgr.get_version_config(ios_channel, android_channel)
    ios_download_url = version_config.get('ios_download_url', None)
    if ios_download_url == '':
        return helpers.show_warn_page(request, '未发现iOS下载版本!')

    android_download_url = version_config.get('android_download_url', None)
    if android_download_url == '':
        return helpers.show_warn_page(request, '未发现安卓下载版本!')

    # 构造上下文
    context = helpers.build_context(request, has_fontawesome = False)
    context['app'] = app
    context['channel'] = channel
    context['ios_download_url'] = ios_download_url
    context['android_download_url'] = android_download_url

    # 渲染页面
    return render(request, 'mweb/registration_v2.html', context)


def api_fetch_smscode(request):
    """ 获取验证码 """
    mobile = request.POST['mobile'].strip()
    if not mobile:
        return ajax.error_response('手机号码不可以为空!')

    sms_code = ''.join([random.choice('0123456789') for _ in range(4)])
    success = sms_mgr.send_sms_code(mobile, sms_code)
    if not success:
        return ajax.error_response('验证码发送失败!')

    return ajax.success_response({}, '验证码已发送')


def api_user_register(request):
    """ 用户注册 """
    mobile = request.POST['mobile'].strip()
    if not mobile:
        return ajax.error_response('手机号码不可以为空!')

    sms_code = request.POST['sms_code'].strip()
    if not sms_code:
        return ajax.error_response('验证码不可以为空!')

    app = request.POST['app'].strip()
    if not app:
        return ajax.error_response('无效的应用名!')

    channel = request.POST['channel'].strip()
    if not channel:
        return ajax.error_response('无效的渠道名!')

    # 检测验证码是否合法
    if not sms_mgr.is_valid_sms_code(mobile, sms_code):
        return ajax.error_response('无效的验证码!')

    # 注册手机号码
    ip = util.get_request_real_ip(request)[0]
    if not registration_mgr.is_registered_mobile(mobile):
        registration_mgr.register_mobile(mobile, app, channel, ip)
    else:
        Log.info(f"Duplicate registered mobile: {mobile}")

    return ajax.success_response({}, '即将开始下载')


# def activity_christmas(request, uid, token):
#     """ 圣诞活动入口 """
#     # 检测token是否合法
#     if not user_mgr.is_valid_token(uid, token):
#         return helpers.show_warn_page(request, '404!')
#
#     context = helpers.build_context(request, has_fontawesome = False)
#     context['uid'] = uid
#     context['token'] = token
#     return render(request, 'mweb/activity/activity_christmas_entry.html', context)


def activity_daily_sign(request, uid, token, env):
    """ 每日签到活动 """
    return redirect(f'https://res.yyzb.com/activity/daily_sign/index.html#/?uid={uid}&token={token}&env={env}')


def activity_chinese_new_year(request, uid, token, env):
    """ 新年活动 """
    return redirect(f'https://res.yyzb.com/activity/chinese_new_year/index.v7.html#/?uid={uid}&token={token}&env={env}')


if __name__ == '__main__':
    print('ok')
